package ui.compose

import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.loadImageBitmap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.net.URL
import java.util.*
import java.util.concurrent.ConcurrentHashMap


/**
 * @author wei kunJie
 * @date 2024/3/7 22:54:05
 */
@Composable
fun NetworkImage(
    url: String,
    painterFor: @Composable (ImageBitmap) -> Painter,
    contentDescription: String,
    modifier: Modifier = Modifier,
    contentScale: ContentScale = ContentScale.Fit,
    defaultPainterFor: Painter
) {
    if (url.isEmpty()) {
        Image(
            painter = defaultPainterFor,
            contentDescription = contentDescription,
            contentScale = contentScale,
            modifier = modifier
        )
        return
    }
    val image: ImageBitmap? by produceState<ImageBitmap?>(null) {
        value = withContext(Dispatchers.IO) {
            try {
                //双重检查
                //先在缓存中找有没有，没有在去下载图片资源
                if (ImageCache.isCache(url)) {//检查1
                    ImageCache.get(url)
                } else {
                    //对同一个url上锁
                    val lock = ImageCache.urlLocks.computeIfAbsent(url) { Any() }
                    synchronized(lock) {
                        if (ImageCache.isCache(url)) {//检查2
                            ImageCache.get(url)//返回给value即image
                        } else {
//                            println("下载图片url:${url}")
                            val loadImageBitmap = loadImageBitmap(URL(url).openStream())
                            //进行图片缓存
                            ImageCache.cache(url, loadImageBitmap)
                            loadImageBitmap//返回给value即image
                        }
                    }
                }
            } catch (e: IOException) {
                e.printStackTrace()
                null//返回给value即image
            }
        }
    }

    if (image != null) {
        //因为 image 是 val 不可变，可能会有image与url不一样的情况，这里手动更正
        if (ImageCache.isCache(url) && ImageCache.get(url) != image) {
            Image(
                painter = painterFor(ImageCache.get(url)!!),
                contentDescription = contentDescription,
                contentScale = contentScale,
                modifier = modifier
            )
        } else {
            Image(
                painter = painterFor(image!!),
                contentDescription = contentDescription,
                contentScale = contentScale,
                modifier = modifier
            )
        }
    } else {
        Image(
            painter = defaultPainterFor,
            contentDescription = contentDescription,
            contentScale = contentScale,
            modifier = modifier
        )
    }
}

object ImageCache {
    private val map = Hashtable<String, ImageBitmap>()
    val urlLocks = ConcurrentHashMap<String, Any>()
    fun get(url: String): ImageBitmap? {
        return map[url]
    }

    fun isCache(url: String): Boolean {
        return map.containsKey(url)
    }

    fun cache(url: String, imageBitmap: ImageBitmap) {
        map[url] = imageBitmap
    }
}